package geppetto.cat.constrains;

import geppetto.cat.models.stats.EStepStats;
import geppetto.cat.programs.ComparePredictedAligmentSets.compareAER;
import geppetto.phraseHMM.Trellis;

public class ConstrainedProjectionStats {
	
	double likelihood=0;
	double objective=0;
	double originalLikelihood=0;
	int totalProjection = 0;
	int totalOfSentenceNoConvergence = 0;
	int totalOfSentenceNoProjection = 0;
	int totalOfSentenceZoomNoStep=0;
	int totalOfSentenceBracketingNoStep=0;
	int totalSentenceWithProjection=0;
	int totalSentencesObjectiveNAN =0;
	int totalOfNoAscentDirectionFound=0;
	int maxProjection = 0;
	int minProjection = 1000;
	int numberfb =0;
	int time=0;
	int maxSteps =0;
	int totalSteps =0;
	Trellis[] lambdas = new Trellis[50];
	int indexNoConverge = -1;
	int[] noConverge;
	
	
	public ConstrainedProjectionStats(){
		noConverge = new int[50];
		java.util.Arrays.fill(noConverge,0);
		lambdas = new Trellis[50];
	}
	
	public String prettyPrint() {
		StringBuffer res = new StringBuffer();
		res.append("\nProjection stats:\n");
		res.append("-log(origL) " + EStepStats.prettyPrint(-originalLikelihood, "0.000E00", 9) +"-log(L) " + 
				EStepStats.prettyPrint(-likelihood, "0.000E00", 9) + " obj " + 
				EStepStats.prettyPrint(objective, "0.000E00", 9) + " time " + 
				EStepStats.formatTime(time) + "\n");
		res.append(" total " + totalProjection + " avg " + EStepStats.prettyPrint(totalProjection*1.0/totalSentenceWithProjection,"0.00",3) + 
				" max " + maxProjection + " min " + minProjection 
				+ " no ascent direction " + totalOfNoAscentDirectionFound + "\n"
				+ " no step zoom " + totalOfSentenceZoomNoStep + " no step bracketing " 
				+ totalOfSentenceBracketingNoStep + " no convergence " + totalOfSentenceNoConvergence + " no violatons " +
				totalOfSentenceNoProjection + " totalObjNAN " + totalSentencesObjectiveNAN + " nfb " + numberfb + " max steps " + 
				maxSteps + " total steps " + totalSteps+ "\n");
		res.append("sentences no cov \n");
		for(int i = 0; i < 50; i++){
			res.append(noConverge[i] + " ");
		}
		//		if (lambdas != null){
//			for(int i = 0; i <50; i++){
//				if (lambdas[i] != null){
//					lambdas[i].printAll();
//				}
//			}
//		}
		return res.toString();	
	}
	
	public void add(SentenceConstrainedProjectionStats stats) {
		time += stats.totalTime;
		double l= Math.log(stats.likelihood);
		if(!Double.isInfinite(l))
			likelihood +=l; 
		originalLikelihood += Math.log(stats.originalLikelihood);
		if(!Double.isInfinite(stats.objective))
			objective += stats.objective;
		numberfb+=stats.fbcall;
		if(stats.noConstrains){
			totalOfSentenceNoProjection++;
		}else if(stats.noZoomStepFound){
			totalOfSentenceZoomNoStep++;
			indexNoConverge++;
			if(indexNoConverge < 50){
				noConverge[indexNoConverge] = stats.sentenceNumber;
				//System.out.println("Adding at pos " + indexNoConverge + " sentenceNumber " + stats.sentenceNumber);
			}
		}else if(stats.noBracketingStepFound){
			indexNoConverge++;
			if(indexNoConverge < 50){
				noConverge[indexNoConverge] = stats.sentenceNumber;
				//System.out.println("Adding at pos " + indexNoConverge + " sentenceNumber " + stats.sentenceNumber);
			}
			totalOfSentenceBracketingNoStep++;
		}else if (stats.noConvergence){
			indexNoConverge++;
			if(indexNoConverge < 50){
				noConverge[indexNoConverge] = stats.sentenceNumber;
				//System.out.println("Adding at pos " + indexNoConverge + " sentenceNumber " + stats.sentenceNumber);
			}
			totalOfSentenceNoConvergence++;
		}else if (stats.objectiveBecomeNotANumber){
			indexNoConverge++;
			if(indexNoConverge < 50){
				noConverge[indexNoConverge] = stats.sentenceNumber;
				//System.out.println("Adding at pos " + indexNoConverge + " sentenceNumber " + stats.sentenceNumber);
			}
			
			totalSentencesObjectiveNAN++;
		}else if (stats.directionNotAscentDirection){
			indexNoConverge++;
			if(indexNoConverge < 50){
				noConverge[indexNoConverge] = stats.sentenceNumber;
				//System.out.println("Adding at pos " + indexNoConverge + " sentenceNumber " + stats.sentenceNumber);
			}
			totalOfNoAscentDirectionFound++;
		}else{
			int nrProjection = stats.numberOfProjections;
			totalProjection += nrProjection;
			totalSentenceWithProjection++;
			if(nrProjection > maxProjection) maxProjection=nrProjection;
			if(nrProjection < minProjection) minProjection=nrProjection;
		}
		if(stats.sentenceNumber < 50){
			lambdas[stats.sentenceNumber] = stats.lambda;
		}
		if(stats.maxStepEval > maxSteps) maxSteps = stats.maxStepEval;
		totalSteps += stats._numberOfSteps.size();
	}
}
